package cn.virens.web.common;

import java.io.Serializable;
import java.util.Collections;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;

import cn.hutool.core.convert.Convert;
import cn.virens.components.page.PageParam;
import cn.virens.components.page.PageParamLayui;
import cn.virens.components.page.PageResult;
import cn.virens.database.common.BaseService;
import cn.virens.exception.ExceptionUtil;
import cn.virens.web.components.spring.permission.Permission;

/**
 * 通用控制器-DataTable
 * 
 * @作者   :cn.loioi
 * @创建时间 :2016年10月13日 下午1:10:43
 */
public abstract class BaseTableController<T, S extends BaseService<T>> extends BaseUserController {
	/** 接口启用标志位 */
	private int enableSymbol = 0xffff;

	/** 添加接口 */
	protected static final int API_CREATE = 0;
	/** 编辑接口 */
	protected static final int API_UPDATE = 1;
	/** 删除接口 */
	protected static final int API_DELETE = 2;

	@Autowired
	protected S mBaseService;

	public BaseTableController(String baseTemplateUrl) {
		super(baseTemplateUrl);
	}

	public BaseTableController(String baseTemplateUrl, String identity) {
		super(baseTemplateUrl, identity);
	}

	/**
	 * 列表页面
	 * 
	 * @param  request
	 * @param  response
	 * @param  model
	 * @return
	 */
	@RequestMapping("index.jspx")
	public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
		checkPermission(request, Permission.VIEW.parts(_identity));// 检查用户的权限是否可以访问

		return returnUrl("index");
	}

	/**
	 * 获取数据接口
	 * 
	 * @param  request
	 * @param  response
	 * @param  model
	 * @return
	 */
	@ResponseBody
	@RequestMapping("list.json")
	public Model list(HttpServletRequest request, Model model) throws Exception {
		checkPermission(request, Permission.VIEW.parts(_identity));// 检查用户的权限是否可以访问

		// 获取分页信息
		PageParam pageParam = PageParamLayui.of(request);
		try {
			PageResult<?> page = listHandle(request, pageParam);

			model.addAttribute("msg", "");
			model.addAttribute("code", "0");
			model.addAttribute("data", page.getList());
			model.addAttribute("count", page.getTotal());
		} catch (Exception e) {
			model.addAttribute("count", 0);
			model.addAttribute("data", Collections.EMPTY_LIST);
			model.addAttribute("code", ExceptionUtil.getCode(e));
			model.addAttribute("msg", ExceptionUtil.getMessage(e));
		}

		return model;
	}

	/**
	 * 添加数据接口
	 * 
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value = "save.json", params = "oper=create")
	public Model create(HttpServletRequest request, HttpServletResponse response, Model model, T record, BindingResult result) throws Exception {
		if (!enable(API_CREATE)) { return renderFail(model, "该接口未开放"); }

		// 检查权限
		checkPermission(request, Permission.MANAGE.parts(_identity));

		// 调用处理
		return createHandle(request, model, record);
	}

	/**
	 * 添加数据接口
	 */
	@ResponseBody
	@RequestMapping(value = "save.json", params = "oper=create", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE })
	public Model createJSON(HttpServletRequest request, HttpServletResponse response, Model model, @RequestBody T record, BindingResult result) throws Exception {
		return create(request, response, model, record, result);
	}

	/**
	 * 修改数据接口
	 * 
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value = "save.json", params = "oper=update")
	public Model update(HttpServletRequest request, HttpServletResponse response, Model model, T record, BindingResult result) throws Exception {
		if (!enable(API_UPDATE)) { return renderFail(model, "该接口未开放"); }

		// 检查权限
		checkPermission(request, Permission.MANAGE.parts(_identity));

		// 调用处理
		return updateHandle(request, model, record);
	}

	/**
	 * 修改数据接口
	 */
	@ResponseBody
	@RequestMapping(value = "save.json", params = "oper=update", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE })
	public Model updateJSON(HttpServletRequest request, HttpServletResponse response, Model model, @RequestBody T record, BindingResult result) throws Exception {
		return update(request, response, model, record, result);
	}

	/**
	 * 删除数据接口
	 * 
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value = "save.json", params = "oper=delete")
	public Model delete(HttpServletRequest request, HttpServletResponse response, Model model, @RequestParam(name = "id", defaultValue = "") String id) throws Exception {
		if (!enable(API_DELETE)) { return renderFail(model, "该接口未开放"); }

		// 检查权限
		checkPermission(request, Permission.MANAGE.parts(_identity));

		// 调用处理
		return deleteHandle(request, model, id);
	}

	/**
	 * 异常操作
	 */
	@ResponseBody
	@RequestMapping(value = "save.json")
	public Model other(Model model) {
		return renderFail(model, "没有有效的请求类型");
	}

	/**
	 * 查询数据库
	 * 
	 * @param  request
	 * @param  pageParam
	 * @return
	 * @throws Exception
	 */
	protected PageResult<?> listHandle(HttpServletRequest request, PageParam pageParam) throws Exception {
		return mBaseService.selectPage(pageParam);
	}

	/**
	 * 添加一条记录
	 * 
	 * @param  request 请求
	 * @param  model   返回
	 * @param  record  数据
	 * @return
	 */
	protected Model createHandle(HttpServletRequest request, Model model, T record) throws Exception {
		log(request, "创建数据：" + JSON.toJSONString(record));

		if (mBaseService.insert(record) != null) {
			return renderSuccess(model, "添加成功");
		} else {
			return renderFail(model, "添加失败");
		}
	}

	/**
	 * 更新一条记录
	 * 
	 * @param  request 请求
	 * @param  model   返回
	 * @param  record  数据
	 * @return
	 */

	protected Model updateHandle(HttpServletRequest request, Model model, T record) throws Exception {
		log(request, "更新数据：" + JSON.toJSONString(record));

		if (mBaseService.update(record) != null) {
			return renderSuccess(model, "更新成功");
		} else {
			return renderFail(model, "更新失败");
		}
	}

	/**
	 * 删除
	 * 
	 * @param  request 请求
	 * @param  model   返回
	 * @param  id
	 * @return
	 */
	protected Model deleteHandle(HttpServletRequest request, Model model, String id) throws Exception {
		log(request, "删除数据：" + id);

		if (mBaseService.delete(toId(id)) > 0) {
			return renderSuccess(model, "成功删除");
		} else {
			return renderFail(model, "删除失败");
		}
	}

	/**
	 * 启用指定接口
	 * 
	 * @param bits 接口标识
	 */
	protected final void enable(int... bits) {
		for (int bit : bits) {
			this.enableSymbol |= (0x0001 << bit);
		}
	}

	/**
	 * 禁用指定接口
	 * 
	 * @param bits 接口标识
	 */
	protected final void disable(int... bits) {
		for (int bit : bits) {
			this.enableSymbol &= ~(0x0001 << bit);
		}
	}

	/**
	 * 获取 指定接口是否启用
	 * 
	 * @param  bit 接口标识
	 * @return
	 */
	protected final boolean enable(int bit) {
		return ((enableSymbol >> bit) & 0x0001) == 0x0001;
	}

	/**
	 * ID 转换
	 * 
	 * @param  id
	 * @return
	 */
	protected Serializable toId(String id) {
		return Convert.toInt(id);
	}
}
